package com.bot.nft.module.dc.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bot.nft.core.enums.chain.ChainLogEnum;
import com.bot.nft.core.enums.dc.NftInfoEnum;
import com.bot.nft.core.enums.dc.NftOrderEnum;
import com.bot.nft.core.enums.dc.RedisEnum;
import com.bot.nft.core.util.NftCodeUtil;
import com.bot.nft.module.dc.domain.*;
import com.bot.nft.module.dc.domain.bo.DcOrderInfoBo;
import com.bot.nft.module.dc.domain.bo.DcOrderQueryListBo;
import com.bot.nft.module.dc.domain.vo.*;
import com.bot.nft.module.dc.mapper.*;
import com.bot.nft.module.dc.service.IDcNftCertService;
import com.bot.nft.module.dc.service.IDcOrderInfoService;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.UUID;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author RenXiaoZheng
 * @since 2024-01-24
 */
@Service
public class DcOrderInfoServiceImpl extends ServiceImpl<DcOrderInfoMapper, DcOrderInfo> implements IDcOrderInfoService {

    //日志
    private static final Log log = LogFactory.get();

    //mapper
    @Resource
    private DcOrderInfoMapper dcOrderMapper;

    //mapper
    @Resource
    private DcPaymentLogMapper dcPaymentLogMapper;

    //mapper
    @Resource
    private DcNftCertMapper dcNtfCertMapper;

    //mapper
    @Resource
    private DcFlowLogMapper dcFlowLogMapper;

    //mapper
    @Resource
    private DcBillLogMapper dcBillLogMapper;

    @Resource
    private DcNftInfoMapper dcNftInfoMapper;

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Resource
    private IDcNftCertService dcNftCertService;

    /**
     * 查询藏品订单
     *
     * @param id
     * @param phone
     * @param name
     * @param status   藏品订单状态
     * @param pageNo   当前第几页
     * @param pageSize 每页显示多少条数据
     * @return
     */
    @Override
    public Page<DcOrderInfoVo> queryDcOrderInfo(String id, String phone, String name, Integer status, Integer pageNo, Integer pageSize) {
        DcOrderInfoServiceImpl.log.info("开始查询藏品订单信息根据订单状态{}", status);
        Page<DcOrderInfoVo> dcOrderPage = new Page<>(pageNo, pageSize);
        Page<DcOrderInfoVo> dcOrderInfoVoPage = dcOrderMapper.selectOrder(id, phone, name, status, dcOrderPage);
        DcOrderInfoServiceImpl.log.info("查询藏品订单信息结束根据订单状态{}", status);
        return dcOrderInfoVoPage;
    }

    /**
     * 查看藏品订单
     *
     * @param id 藏品订单标识
     * @return
     */
    @Override
    public DcOrderInfoVo getDcOrderInfo(String id) {
        DcOrderInfoServiceImpl.log.info("根据藏品订单标识{}查看藏品订单信息", id);
        //根基藏品订单id查看藏品订单信息
        DcOrderInfoVo dcOrderInfoVo = dcOrderMapper.getDcOrder(id);
        //拼写查询藏品支付信息
        String status = dcOrderInfoVo.getStatus();
        if (status == null) return dcOrderInfoVo;
        //订单支付信息查询
        QueryWrapper<DcPaymentLog> parWrapper = new QueryWrapper<>();
        //订单支付信息查询
        parWrapper.lambda().eq(DcPaymentLog::getOrderId, id);
        //查询
        List<DcPaymentLogVo> dcPaymentLogVos = dcPaymentLogMapper.selectVoList(parWrapper);
        //藏品证书信息查询
        QueryWrapper<DcNftCert> certWrapper = new QueryWrapper<>();
        //藏品证书信息查询
        certWrapper.lambda().eq(DcNftCert::getId, dcOrderInfoVo.getCertId());
        //查询藏品证书
        DcNftCertVo dcNftCertVo = dcNtfCertMapper.selectVoOne(certWrapper);
        //查看藏品证书信息
        dcOrderInfoVo.setDcNftCertVo(dcNftCertVo);
        dcOrderInfoVo.setDcPaymentLogVos(dcPaymentLogVos);
        DcOrderInfoServiceImpl.log.info("结束查看藏品订单信息", id);
        return dcOrderInfoVo;
    }

    /**
     * 取消藏品订单
     *
     * @param id 藏品订单标识 根据藏品订单标识取消藏品订单
     * @return
     */
    @Override
    public Boolean cancelDcNftInfo(String id) {
        DcOrderInfoServiceImpl.log.info("根据藏品订单标识{}取消藏品订单", id);
        //根基藏品订单id查看藏品订单信息
        DcOrderInfoVo dcOrderInfoVo = dcOrderMapper.getDcOrder(id);
        Integer code = dcOrderInfoVo.getCode();
        String nftId = dcOrderInfoVo.getNftId();
        redisTemplate.boundListOps(RedisEnum.KEY.getValue() + nftId).leftPush(code);
        DcOrderInfo dcOrderInfo = new DcOrderInfo();
        dcOrderInfo.setId(id);
        dcOrderInfo.setCode(null);
        dcOrderInfo.setStatus(NftInfoEnum.NFT_BELOW.getValue());
        int i = dcOrderMapper.updateById(dcOrderInfo);
        //取消订单添加库存
        DcNftInfoVo dcNftInfoVo = dcNftInfoMapper.selectVoById(nftId);
        Integer inventory = Integer.valueOf(dcNftInfoVo.getInventory());
        Integer NftInventory = inventory + 1;
        DcNftInfo dcNftInfo = new DcNftInfo();
        dcNftInfo.setId(id);
        dcNftInfo.setInventory(NftInventory);
        dcNftInfoMapper.updateById(dcNftInfo);
        DcOrderInfoServiceImpl.log.info("取消藏品订单{}成功", id);
        return i > 0;
    }

    /**
     * 支付藏品订单
     *
     * @param id 藏品订单标识 根据藏品订单标识支付藏品订单
     * @return
     */
    @Override
    public Boolean paymentDcNftInfo(String id) {
        //支付藏品订单
        //根基藏品订单id查看藏品订单信息
        DcOrderInfoVo dcOrderInfoVo = dcOrderMapper.getDcOrder(id);
        Integer status = Integer.valueOf(dcOrderInfoVo.getStatus());//获取藏品订单状态
        if (status == NftInfoEnum.NFT_BELOW.getValue()) {
            return false;
        }
        int insert = 0;
        //调用支付接口
        if (insert == 0) {
            DcNftCert dcNtfCert = dcNftCertService.genCert(dcOrderInfoVo.getNftId(), dcOrderInfoVo.getMbId(), ChainLogEnum.BUSINESS_PURCHASE.getValue());
            insert = dcNtfCertMapper.insert(dcNtfCert);//添加藏品证书
            DcOrderInfo dcOrderInfo = new DcOrderInfo();
            dcOrderInfo.setId(id);
            dcOrderInfo.setCertId(dcNtfCert.getId());
            dcOrderInfo.setStatus(NftOrderEnum.NFT_ORDER_OK.getValue());
            dcOrderMapper.updateById(dcOrderInfo);
            DcPaymentLog dcPaymentLog = new DcPaymentLog();//生成藏品支付信息
            dcPaymentLog.setId(IdUtil.getSnowflakeNextIdStr());
            dcPaymentLog.setPayment(dcOrderInfoVo.getRealityAmount());//订单实付金额
            dcPaymentLog.setMdId(dcOrderInfoVo.getMbId());//会员标识
            dcPaymentLog.setOrderId(dcOrderInfoVo.getId());
            dcPaymentLog.setPayDate(new DateTime());
            dcPaymentLog.setPayType(NftOrderEnum.NFT_PAY_WAY.getValue());//支付类型
            dcPaymentLog.setPayWay(NftOrderEnum.NFT_PAY_TYPE.getValue());//支付方式
            dcPaymentLog.setOutFlowNo(String.valueOf(UUID.randomUUID()));//交易流水号
            insert = dcPaymentLogMapper.insert(dcPaymentLog);
            //生成流转记录信息
            DcFlowLog dcFlowLog = new DcFlowLog();
            dcFlowLog.setId(IdUtil.getSnowflakeNextIdStr());
            dcFlowLog.setFlowTime(new DateTime());//流转时间
            dcFlowLog.setMbId(dcOrderInfoVo.getMbId());//会员标识
            dcFlowLog.setCertId(dcNtfCert.getId());//藏品证书标识
            dcFlowLog.setCirculation(NftOrderEnum.NFT_FLOW.getValue());
            insert = dcFlowLogMapper.insert(dcFlowLog);//添加藏品流转记录
            DcBillLog dcBillLog = new DcBillLog();//生成交易账单信息
            dcBillLog.setId(IdUtil.getSnowflakeNextIdStr());
            dcBillLog.setRecordTime(new DateTime());//记录时间
            dcBillLog.setType(NftOrderEnum.ORDER_OK.getValue());//收支类型
            dcBillLog.setTrader(dcOrderInfoVo.getMbId());//交易人标识
            dcBillLog.setChangeAmount(dcOrderInfoVo.getRealityAmount());//变动金额
            dcBillLog.setRemark(NftOrderEnum.NFT_UNIT.getName());
            insert = dcBillLogMapper.insert(dcBillLog);
        }
        return insert > 0;
    }

    /**
     * 购买藏品
     *
     * @param dcOrderInfoBo 藏品订单
     * @return
     */
    @Override
    public DcOrderInfoVo orderDcNftInfo(DcOrderInfoBo dcOrderInfoBo) {
        DcOrderInfoServiceImpl.log.info("购买订单时添加藏品信息跟藏品");
        //购买订单时添加藏品信息跟藏品
        //新建entti
        DcOrderInfo orderInfo = BeanUtil.toBean(dcOrderInfoBo, DcOrderInfo.class);
        //添加状态为待支付
        orderInfo.setStatus(NftOrderEnum.ORDER_SALE_NUM.getValue());
        dcOrderMapper.insert(orderInfo);
        DcOrderInfoServiceImpl.log.info("生成订单完成");
        DcOrderInfoVo dcOrderInfoVo = dcOrderMapper.selectVoById(orderInfo.getId());
        DcOrderInfoServiceImpl.log.info("返回订单信息");
        return dcOrderInfoVo;
    }

    /**
     * @param dcOrderQueryListBo
     * @param pageNo
     * @param pageSize
     * @return
     */
    @Override
    public Page<DcOrderVo> queryOrder(DcOrderQueryListBo dcOrderQueryListBo, Integer pageNo, Integer pageSize) {
        Page<DcOrderVo> page = new Page<>(pageNo, pageSize);
        Page<DcOrderVo> dcOrderVoPage = dcOrderMapper.queryOrder(page, dcOrderQueryListBo.getPhone(), dcOrderQueryListBo.getType(), dcOrderQueryListBo.getStatus(), dcOrderQueryListBo.getName(), dcOrderQueryListBo.getStartTime(), dcOrderQueryListBo.getEndTime());
        return dcOrderVoPage;
    }

    /**
     * 购买藏品
     *
     * @param id   藏品证书标识
     * @param mbId 购买人标识
     * @return
     */
    @Override
    public DcOrderInfoVo buyDcNftInfo(String id, String mbId) {
        //查询是否有订单
        //构建条件
        DcOrderInfoVo dcOrderVo = dcOrderMapper.getDcOrder(id);
        if (ObjectUtil.isNotNull(dcOrderVo)) {
            return dcOrderVo;
        }
        DcOrderInfoServiceImpl.log.info("购买订单时添加藏品信息跟藏品");
        //购买订单时添加藏品信息跟藏品
        DcNftInfoVo dcNftInfoVo = dcNftInfoMapper.selectVoById(id);
        //新建entti
        String nftId = dcNftInfoVo.getId();
        DcOrderInfo orderInfo = new DcOrderInfo();
        //获取藏品编号
        Integer publishNum = Integer.valueOf(dcNftInfoVo.getPublishNum());
        List<Integer> codeList = new ArrayList<>();
        for (int i = 1; i <= publishNum; i++ ) {
            codeList.add(i);
        }
        Collections.shuffle(codeList);
        redisTemplate.boundListOps(RedisEnum.KEY.getValue() + nftId).leftPushAll(codeList.toArray());
        //生成藏品证书编号
        //生成藏品证书编号
        Integer code = (Integer) redisTemplate.boundListOps(RedisEnum.KEY.getValue() + nftId).rightPop();
        //添加状态为待支付
        orderInfo.setId(IdUtil.getSnowflakeNextIdStr());
        orderInfo.setNftId(id);
        orderInfo.setMbId(mbId);
        orderInfo.setCode(code);
        orderInfo.setOrderAmount(dcNftInfoVo.getPrice());
        orderInfo.setUnitPrice(dcNftInfoVo.getPrice());
        orderInfo.setCreateUser("pingtai");
        orderInfo.setCreateTime(new DateTime());
        orderInfo.setNum(NftOrderEnum.NFT_ORDER_OK.getValue());
        orderInfo.setStatus(NftOrderEnum.ORDER_SALE_NUM.getValue());
        dcOrderMapper.insert(orderInfo);
        DcOrderInfoServiceImpl.log.info("生成订单完成");
        //生成藏品订单后减去库存
        Integer inventory = Integer.valueOf(dcNftInfoVo.getInventory());
        Integer NftInventory = inventory - 1;
        DcNftInfo dcNftInfo = new DcNftInfo();
        dcNftInfo.setId(id);
        dcNftInfo.setInventory(NftInventory);
        int i = dcNftInfoMapper.updateById(dcNftInfo);
        DcOrderInfoVo dcOrderInfoVo = dcOrderMapper.getDcOrder(orderInfo.getId());
        DcOrderInfoServiceImpl.log.info("返回订单信息");
        return dcOrderInfoVo;
    }

    /**
     * 查看订单集合
     *
     * @return
     */
    @Override
    public List<DcOrderInfo> selectOrder() {
        QueryWrapper<DcOrderInfo> dcNftInfoQueryWrapper = new QueryWrapper<>();
        dcNftInfoQueryWrapper.lambda().eq(DcOrderInfo::getStatus, "2");
        //返回藏品订单集合
        List<DcOrderInfo> dcOrderInfos = dcOrderMapper.selectList(dcNftInfoQueryWrapper);
        return dcOrderInfos;
    }


}
